'''
    Python程序中的异常不仅可以自动触发,还可以由开发人员使用raise语句和assert语句主动抛出
'''

# 9.3.1 使用raise语句抛出异常
# 在python中使用raise语句可以显示地抛出异常,raise语句的语法格式如下:

# 1.使用异常类引发异常
# 使用"raise异常类"语句可以引发该语句中异常类对应的异常,示例代码如下:
# raise IndexError
# 运行结果如下:
'''
Traceback (most recent call last):
  File "D:/code/python/blackhorse_test/chapter_9 异常/9.3 抛出异常.py", line 9, in <module>
    raise IndexError
IndexError
'''
# "raise 异常类"语句在执行时会先隐式地创建该语句中异常类的实力,然后才引发异常.

# 2.使用异常类对象引发异常
# 使用"raise 异常类对象"语句可以引发该语句中异常类对象对应的异常,示例代码如下:
# raise IndexError()
# 运行结果如下:
'''
Traceback (most recent call last):
  File "D:/code/python/blackhorse_test/chapter_9 异常/9.3 抛出异常.py", line 22, in <module>
    raise IndexError()
IndexError
'''
# 以上代码中raise之后的IndexError()用于创建异常类对象.创建异常类对象时还通过字符串指定异常的具体信息,示例代码如下
# raise IndexError('索引超出下标范围')   # 抛出异常及其具体信息
# 运行代码,结果如下:
'''
Traceback (most recent call last):
  File "D:/code/python/blackhorse_test/chapter_9 异常/9.3 抛出异常.py", line 31, in <module>
    raise IndexError('索引超出下标范围')   # 抛出异常及其具体信息
IndexError: 索引超出下标范围
'''

# 3.重新引发异常
# 使用不带任何参数的"raise"语句可以引发刚刚发生过的异常,示例代码如下:
# try:
#     raise IndexError('索引下标超出范围')
# except:
#     raise
'''
以上示例中的try语句执行后会出现因raise语句引发的IndexError异常,except子句会被执行;except子句后的代码又使用raise语句抛出杠杆发生的IndexError
异常,最终程序因再次抛出异常而终止执行
'''
'''
Traceback (most recent call last):
  File "D:/code/python/blackhorse_test/chapter_9 异常/9.3 抛出异常.py", line 44, in <module>
    raise IndexError('索引下标超出范围')
IndexError: 索引下标超出范围
'''

'''
9.3.2 使用assert语句抛出异常
'''
# assert语句又称为断言语句,其语法格式如下:
# assert 表达式,异常信息
# 以上语法格式的assert后面紧跟一个表达式,表达式的值为False时触发AssertionError异常,值为True时不做任何操作;表达式之后可以用字符串来描述异常信息
# assert语句可以帮助程序开发者在开发阶段调试程序,以保证程序能够正确运行,下面使用断言语句判断用户输入的除数是否为0,示例代码如下:

# num_one = int(input('请输入被除数'))
# num_two = int(input('请输入除数'))
# assert num_two != 0 ,'除数不能为0' # assert语句后判定为True时往下运行,为False时抛出异常
# result = num_one / num_two
# print(result)

'''
9.3.3 异常的传递
    如果程序中的异常没有被处理,默认情况下会将该异常传递到上一级,如果上一级仍然没有处理异常,那么会继续向上传递,直至异常被处理或程序崩溃
    下面通过一个计算正方形面积的示例来演示异常的传递,该示例由gei_width(),calc_area()和show_area()共3个函数组成.其中get_width()函数
用于计算正方形边长,calc_area()函数用于计算正方形面积,show_area()函数用于输出正方形的面积.具体代码如下:
'''
def get_width():
    print('get_width开始执行')
    num = int(input('请输入除数:'))
    width_len = 10 / num
    print('get_width执行结束')
    return width_len
def calc_area():
    print('calc_area开始执行')
    width_len = get_width()
    print('calc_area执行结束')
    return width_len**2
def show_area():
    try:
        print('show_area开始执行')
        area_val = calc_area()
        print(f'正方形面积是{area_val}')
        print('show_area执行结束')
    except Exception as e:
        print(f'捕捉到异常{e}')
show_area()
'''
    get_width()函数使用变量num接收用户输入的除数,通过语句width_len = 10 / num计算正方形的边长,如果输入0,程序引发ZeroDivisionError异常,由于
get_width()函数中没有捕获异常的语句,所以get_width()函数中引发的异常向上传递到calc_area()函数,calc_area()函数中也没有捕获异常的语句,只能将
异常继续向上传递到show_area()函数
    show_area()函数中设置了异常捕获语句try-except,它在接收到由calc_area()函数传递的异常后,会通过try-except捕获并处理异常.
'''
'''
show_area开始执行
calc_area开始执行
get_width开始执行
请输入除数:0
捕捉到异常division by zero

'''